package ixRedis

import (
	"context"
	"encoding/json"
	"time"
)

// CacheDecorator 缓存装饰器
type CacheDecorator struct {
	client *Client
	prefix string
	ttl    time.Duration
}

// NewCacheDecorator 创建缓存装饰器
func (c *Client) NewCacheDecorator(prefix string, ttl time.Duration) *CacheDecorator {
	return &CacheDecorator{
		client: c,
		prefix: prefix,
		ttl:    ttl,
	}
}

// GetOrSet 获取缓存，如果不存在则设置
func (cd *CacheDecorator) GetOrSet(ctx context.Context, key string, dest interface{}, setter func() (interface{}, error)) error {
	cacheKey := cd.prefix + ":" + key

	// 尝试从缓存获取
	exists, err := cd.client.Get(cacheKey, dest)
	if err != nil {
		return err
	}

	if exists {
		return nil
	}

	// 缓存不存在，调用设置函数
	value, err := setter()
	if err != nil {
		return err
	}

	// 设置到缓存
	err = cd.client.SetWithExpire(cacheKey, value, cd.ttl)
	if err != nil {
		return err
	}

	// 将值复制到目标变量
	return cd.copyValue(value, dest)
}

// GetOrSetWithCallback 获取缓存，如果不存在则调用回调函数设置
func (cd *CacheDecorator) GetOrSetWithCallback(ctx context.Context, key string, dest interface{}, callback func() (interface{}, error)) error {
	return cd.GetOrSet(ctx, key, dest, callback)
}

// Set 设置缓存
func (cd *CacheDecorator) Set(key string, value interface{}) error {
	cacheKey := cd.prefix + ":" + key
	return cd.client.SetWithExpire(cacheKey, value, cd.ttl)
}

// Get 获取缓存
func (cd *CacheDecorator) Get(key string, dest interface{}) (bool, error) {
	cacheKey := cd.prefix + ":" + key
	return cd.client.Get(cacheKey, dest)
}

// Delete 删除缓存
func (cd *CacheDecorator) Delete(key string) error {
	cacheKey := cd.prefix + ":" + key
	_, err := cd.client.Del(cacheKey)
	return err
}

// DeletePattern 删除匹配模式的缓存
func (cd *CacheDecorator) DeletePattern(pattern string) error {
	keys, err := cd.client.Keys(cd.prefix + ":" + pattern)
	if err != nil {
		return err
	}

	if len(keys) > 0 {
		_, err = cd.client.Del(keys...)
	}
	return err
}

// Clear 清空所有缓存
func (cd *CacheDecorator) Clear() error {
	return cd.DeletePattern("*")
}

// copyValue 复制值到目标变量
func (cd *CacheDecorator) copyValue(src, dest interface{}) error {
	// 使用JSON序列化/反序列化来复制值
	jsonData, err := json.Marshal(src)
	if err != nil {
		return err
	}
	return json.Unmarshal(jsonData, dest)
}

// CacheStats 缓存统计信息
type CacheStats struct {
	HitCount  int64
	MissCount int64
	SetCount  int64
	DelCount  int64
}

// StatsCacheDecorator 带统计的缓存装饰器
type StatsCacheDecorator struct {
	*CacheDecorator
	stats CacheStats
}

// NewStatsCacheDecorator 创建带统计的缓存装饰器
func (c *Client) NewStatsCacheDecorator(prefix string, ttl time.Duration) *StatsCacheDecorator {
	return &StatsCacheDecorator{
		CacheDecorator: c.NewCacheDecorator(prefix, ttl),
		stats:          CacheStats{},
	}
}

// GetOrSet 获取缓存，如果不存在则设置（带统计）
func (scd *StatsCacheDecorator) GetOrSet(ctx context.Context, key string, dest interface{}, setter func() (interface{}, error)) error {
	cacheKey := scd.prefix + ":" + key

	// 尝试从缓存获取
	exists, err := scd.client.Get(cacheKey, dest)
	if err != nil {
		return err
	}

	if exists {
		scd.stats.HitCount++
		return nil
	}

	scd.stats.MissCount++

	// 缓存不存在，调用设置函数
	value, err := setter()
	if err != nil {
		return err
	}

	// 设置到缓存
	err = scd.client.SetWithExpire(cacheKey, value, scd.ttl)
	if err != nil {
		return err
	}

	scd.stats.SetCount++

	// 将值复制到目标变量
	return scd.copyValue(value, dest)
}

// GetStats 获取统计信息
func (scd *StatsCacheDecorator) GetStats() CacheStats {
	return scd.stats
}

// ResetStats 重置统计信息
func (scd *StatsCacheDecorator) ResetStats() {
	scd.stats = CacheStats{}
}
